"""
Authentication API Routes
=========================

API endpoints for user authentication and authorization.
Handles registration, login, logout, and token refresh.
"""

from flask import Blueprint, request, jsonify
from app.services.auth_service import auth_service
from app.utils.validators import validate_registration, validate_login
from app.utils.jwt_handler import jwt_handler
from app.utils.response_formatter import format_response

# Create authentication blueprint
auth_bp = Blueprint('auth', __name__)

@auth_bp.route('/register', methods=['POST'])
def register():
    """
    User registration endpoint.
    
    Request Body:
        {
            "username": "string",
            "email": "string",
            "password": "string",
            "first_name": "string (optional)",
            "last_name": "string (optional)"
        }
    
    Returns:
        {
            "status": "success",
            "message": "User registered successfully",
            "data": {
                "user": {...},
                "tokens": {...}
            }
        }
    """
    try:
        # Get request data
        data = request.get_json()
        
        if not data:
            return format_response(
                status='error',
                message='Request body is required',
                error_code='missing_data',
                status_code=400
            )
        
        # Validate input
        is_valid, validation_result = validate_registration(data)
        if not is_valid:
            return format_response(
                status='error',
                message='Validation failed',
                error_code='validation_error',
                data=validation_result,
                status_code=400
            )
        
        # Register user
        success, result = auth_service.register_user(
            username=data['username'],
            email=data['email'],
            password=data['password'],
            first_name=data.get('first_name'),
            last_name=data.get('last_name')
        )
        
        if success:
            return format_response(
                status='success',
                message=result['message'],
                data=result
            )
        else:
            return format_response(
                status='error',
                message=result['error'],
                error_code=result['error_code'],
                status_code=400
            )
    
    except Exception as e:
        return format_response(
            status='error',
            message='Registration failed',
            error_code='internal_error',
            status_code=500
        )

@auth_bp.route('/login', methods=['POST'])
def login():
    """
    User login endpoint.
    
    Request Body:
        {
            "username_or_email": "string",
            "password": "string",
            "remember_me": "boolean (optional)"
        }
    
    Returns:
        {
            "status": "success",
            "message": "Login successful",
            "data": {
                "user": {...},
                "tokens": {...}
            }
        }
    """
    try:
        # Get request data
        data = request.get_json()
        
        if not data:
            return format_response(
                status='error',
                message='Request body is required',
                error_code='missing_data',
                status_code=400
            )
        
        # Validate input
        is_valid, validation_result = validate_login(data)
        if not is_valid:
            return format_response(
                status='error',
                message='Validation failed',
                error_code='validation_error',
                data=validation_result,
                status_code=400
            )
        
        # Login user
        success, result = auth_service.login_user(
            username_or_email=data['username_or_email'],
            password=data['password'],
            remember_me=data.get('remember_me', False)
        )
        
        if success:
            return format_response(
                status='success',
                message=result['message'],
                data=result
            )
        else:
            status_code = 401
            if result['error_code'] in ['account_locked', 'account_inactive']:
                status_code = 403
            
            return format_response(
                status='error',
                message=result['error'],
                error_code=result['error_code'],
                data={k: v for k, v in result.items() if k not in ['error', 'error_code']},
                status_code=status_code
            )
    
    except Exception as e:
        return format_response(
            status='error',
            message='Login failed',
            error_code='internal_error',
            status_code=500
        )

@auth_bp.route('/logout', methods=['POST'])
def logout():
    """
    User logout endpoint.
    
    Headers:
        Authorization: Bearer <access_token>
    
    Returns:
        {
            "status": "success",
            "message": "Logout successful"
        }
    """
    try:
        # Get token from header
        auth_header = request.headers.get('Authorization')
        token = jwt_handler.extract_token_from_header(auth_header)
        
        if not token:
            return format_response(
                status='error',
                message='Authorization token is required',
                error_code='missing_token',
                status_code=401
            )
        
        # Logout user
        success, result = auth_service.logout_user(token)
        
        if success:
            return format_response(
                status='success',
                message=result['message']
            )
        else:
            return format_response(
                status='error',
                message=result['error'],
                error_code=result['error_code'],
                status_code=401
            )
    
    except Exception as e:
        return format_response(
            status='error',
            message='Logout failed',
            error_code='internal_error',
            status_code=500
        )

@auth_bp.route('/refresh', methods=['POST'])
def refresh_token():
    """
    Token refresh endpoint.
    
    Request Body:
        {
            "refresh_token": "string"
        }
    
    Returns:
        {
            "status": "success",
            "message": "Token refreshed successfully",
            "data": {
                "tokens": {...}
            }
        }
    """
    try:
        # Get request data
        data = request.get_json()
        
        if not data or 'refresh_token' not in data:
            return format_response(
                status='error',
                message='Refresh token is required',
                error_code='missing_refresh_token',
                status_code=400
            )
        
        # Refresh token
        success, result = auth_service.refresh_token(data['refresh_token'])
        
        if success:
            return format_response(
                status='success',
                message=result['message'],
                data=result
            )
        else:
            return format_response(
                status='error',
                message=result['error'],
                error_code=result['error_code'],
                status_code=401
            )
    
    except Exception as e:
        return format_response(
            status='error',
            message='Token refresh failed',
            error_code='internal_error',
            status_code=500
        )

@auth_bp.route('/password/reset-request', methods=['POST'])
def request_password_reset():
    """
    Request password reset endpoint.
    
    Request Body:
        {
            "email": "string"
        }
    
    Returns:
        {
            "status": "success",
            "message": "If the email exists, a reset link has been sent"
        }
    """
    try:
        # Get request data
        data = request.get_json()
        
        if not data or 'email' not in data:
            return format_response(
                status='error',
                message='Email is required',
                error_code='missing_email',
                status_code=400
            )
        
        # Request password reset
        success, result = auth_service.request_password_reset(data['email'])
        
        # Always return success for security (don't reveal if email exists)
        return format_response(
            status='success',
            message=result['message']
        )
    
    except Exception as e:
        return format_response(
            status='error',
            message='Password reset request failed',
            error_code='internal_error',
            status_code=500
        )

@auth_bp.route('/password/reset', methods=['POST'])
def reset_password():
    """
    Reset password endpoint.
    
    Request Body:
        {
            "token": "string",
            "new_password": "string"
        }
    
    Returns:
        {
            "status": "success",
            "message": "Password reset successful"
        }
    """
    try:
        # Get request data
        data = request.get_json()
        
        if not data:
            return format_response(
                status='error',
                message='Request body is required',
                error_code='missing_data',
                status_code=400
            )
        
        # Validate required fields
        if 'token' not in data or 'new_password' not in data:
            return format_response(
                status='error',
                message='Token and new password are required',
                error_code='missing_fields',
                status_code=400
            )
        
        # Reset password
        success, result = auth_service.reset_password(
            token=data['token'],
            new_password=data['new_password']
        )
        
        if success:
            return format_response(
                status='success',
                message=result['message']
            )
        else:
            return format_response(
                status='error',
                message=result['error'],
                error_code=result['error_code'],
                status_code=400
            )
    
    except Exception as e:
        return format_response(
            status='error',
            message='Password reset failed',
            error_code='internal_error',
            status_code=500
        )

@auth_bp.route('/verify', methods=['GET'])
def verify_token():
    """
    Verify authentication token endpoint.
    
    Headers:
        Authorization: Bearer <access_token>
    
    Returns:
        {
            "status": "success",
            "message": "Token is valid",
            "data": {
                "user": {...}
            }
        }
    """
    try:
        # Get token from header
        auth_header = request.headers.get('Authorization')
        token = jwt_handler.extract_token_from_header(auth_header)
        
        if not token:
            return format_response(
                status='error',
                message='Authorization token is required',
                error_code='missing_token',
                status_code=401
            )
        
        # Verify token
        payload = jwt_handler.verify_token(token)
        
        if not payload:
            return format_response(
                status='error',
                message='Invalid or expired token',
                error_code='invalid_token',
                status_code=401
            )
        
        # Get user info
        user_id = payload.get('user_id')
        from app.models.user import User
        
        user = User.find_by_username(payload.get('username'))
        
        if not user:
            return format_response(
                status='error',
                message='User not found',
                error_code='user_not_found',
                status_code=404
            )
        
        return format_response(
            status='success',
            message='Token is valid',
            data={
                'user': user.to_dict()
            }
        )
    
    except Exception as e:
        return format_response(
            status='error',
            message='Token verification failed',
            error_code='internal_error',
            status_code=500
        )